package service.arbitrator;

import java.util.HashMap;
import java.util.Map;
import common.Point;
import common.Settings;
import common.SignedData;
import common.UserRPCClient;

import iface.ArbitratorsBoardServiceInterface;
import java.util.Random;

public class ArbitratorBoardService implements ArbitratorsBoardServiceInterface {
    // fields

    Map<Integer, Arbitrator> arbitrators;
    Map<Integer, ArbitratorDetails> arbitratorsDetails;
    Random random;
    // signatures
    //SignatureVerifier CASignatureVerifier;
    public byte[] caPublicKey;
    // services
    UserRPCClient forumServerWebService;
    UserRPCClient CAWebService;

    public ArbitratorBoardService() {
        this.arbitrators = new HashMap<Integer, Arbitrator>();
        this.arbitratorsDetails = new HashMap<Integer, ArbitratorDetails>();
        random = new Random();
        createArbitrators(Settings.numberOfArbitratoras);
        setCAWebService();
        setforumServerWebService();
        this.caPublicKey = null;
    }

    private void createArbitrators(int numberOfArbitrators) {
        for (int i = 0; i < numberOfArbitrators; i++) {
            addArbitrator(i, new Arbitrator(i));
        }
    }

    private void setCAWebService() {
        this.CAWebService = new UserRPCClient(Settings.CA_URI);
    }

    private void setforumServerWebService() {
        this.forumServerWebService = new UserRPCClient(Settings.SERVER_URI);
    }

    private byte[] getCAPublicKey() {
        Class[] returnTypes = new Class[]{byte[].class};
        String namespaceURI = Settings.CA_NS;
        String methodName = "getPublicKeyEncoding";
        Object[] mArgs = null;
        return (byte[]) this.CAWebService.wsCall(returnTypes, namespaceURI, methodName, mArgs)[0];
    }

    public Boolean addArbitrator(Integer arbitratorID, Arbitrator arbitrator) {
        if (!this.arbitrators.containsKey(arbitratorID)) {
            this.arbitrators.put(arbitratorID, arbitrator);
            ArbitratorDetails ad = new ArbitratorDetails();
            ad.setArbitratorID(arbitratorID);
            ad.setUserScore(random.nextInt(5) + 1);
            ad.setServerScore(random.nextInt(5) + 1);
            this.arbitratorsDetails.put(arbitratorID, ad);
            return true;
        }
        return false;
    }

    @Override
    public ArbitratorDetails[] getArbitrators() {
        return this.arbitratorsDetails.values().toArray(new ArbitratorDetails[0]);
    }

    @Override
    public Boolean arbitrate(Integer arbitratorID, Integer tmpUserID,
            String message, byte[] signature) {
        Arbitrator arbitrator = this.arbitrators.get(arbitratorID);
        if (arbitrator == null) {
            return true;
        }
        return arbitrator.arbitrate(tmpUserID, message, signature);
    }

    @Override
    public byte[] initServerSession(Integer arbitratorID, int userID) {

        Arbitrator arbitrator = this.arbitrators.get(arbitratorID);
        if (arbitrator == null) {
            return (byte[]) null;
        }
        return arbitrator.initServerSession(userID);
    }

    @Override
    public byte[] initUserSession(Integer arbitratorID, Integer tmpUserID,
            byte[] IDSignature, String[] commitmentsAsString,
            SignedData[] commitmentsSignatures, Point share) {

        if (null == this.caPublicKey) {
            this.caPublicKey = this.getCAPublicKey();
            setPublicCAKeyToArbitrators();
        }

        Arbitrator arbitrator = this.arbitrators.get(arbitratorID);
        if (arbitrator == null) {
            return (byte[]) null;
        }

        // this line should be deleted!!!!!!
        // setPublicCAKeyToArbitrators();//////
        ////////////////////////////////////

        return arbitrator.initUserSession(tmpUserID, IDSignature, commitmentsAsString, commitmentsSignatures, share);
    }

    private void setPublicCAKeyToArbitrators() {
        for (Arbitrator arbitrator : this.arbitrators.values()) {
            arbitrator.setCASignatureVerifier(this.caPublicKey);
        }

    }
}
